/*******************************************************************************
 * Copyright (c) 2011 Irineu Martins de Lima Moura (imlm2).
 * This file is part of JBeat.
 * 
 *     JBeat is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     JBeat is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with JBeat.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Irineu Martins de Lima Moura (imlm2) - initial API and implementation
 ******************************************************************************/
package br.ufpe.cin.imlm2.jbeat.soot.common;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.util.Chain;

/**
 * A wrapper for the soot Scene with facility methods to query for SootClass and SootMethod 
 * objects and other utility methods.
 * @author irineu
 *
 */
public class SceneWrapper {


	/**
	 * Returns all the concrete classes found in the Scene.
	 * @return
	 */
	public static Collection<SootClass> getConcreteClasses(){
		Chain<SootClass> allClasses = Scene.v().getClasses();
		Set<SootClass> classes = new HashSet<SootClass>();
		for (SootClass sootClass : allClasses) {
			if(sootClass.isConcrete()){
				classes.add(sootClass);
			}
		}
		return classes;
	}

	/**
	 * Return all the abstract classes (that are not interfaces) in the Scene.
	 * @return
	 */
	public static Collection<SootClass> getAbstractClasses(){
		Chain<SootClass> allClasses = Scene.v().getClasses();
		Set<SootClass> classes = new HashSet<SootClass>();
		for (SootClass sootClass : allClasses) {
			if(!sootClass.isConcrete() && !sootClass.isInterface()){
				classes.add(sootClass);
			}
		}
		return classes;
	}

	/**
	 * Return all classes (concrete and abstract) and interfaces in the Scene.
	 * @return
	 */
	public static Collection<SootClass> getAllClassesAndInterfaces(){
		return new HashSet<SootClass>(Scene.v().getClasses());
	}

	/**
	 * Returns all methods (concrete or abstracts) in the Scene.
	 * @return
	 */
	public static Collection<SootMethod> getAllMethods(){
		List<SootMethod> allMeths = new ArrayList<SootMethod>();
		Collection<SootClass> classes = SceneWrapper.getAllClassesAndInterfaces();
		for (SootClass sootClass : classes) {
			allMeths.addAll(sootClass.getMethods());
		}
		return allMeths;
	}
	
	/**
	 * Returns all the concrete methods in the Scene.
	 * @return
	 */
	public static Collection<SootMethod> getConcreteMethods(){
		Collection<SootMethod> allMeths = getAllMethods();
		Iterator<SootMethod> it = allMeths.iterator();
		while(it.hasNext()) if(!it.next().isConcrete()) it.remove();
		return allMeths;
	}

}
